package com.websocket.t_io.websocket;
import java.util.*;
import com.alibaba.fastjson.JSON;
import com.websocket.constant.RedisConstant;
import com.websocket.dto.DialogueListForUserinfo;
import com.websocket.dto.WebsocketDTO;
import com.websocket.dto.WechatDTO;
import com.websocket.dto.DialogueList;
import com.websocket.entity.UserInfo;
import com.websocket.entity.User_;
import com.websocket.enums.FlagEnum;
import com.websocket.repository.UserInfoRepository;
import com.websocket.repository.mongo.DialogueListRepository;
import com.websocket.repository.mongo.OtoWechatRepository;
import com.websocket.service.Impl.OtoWechatServiceImpl;
import com.websocket.service.Impl.UserServiceImpl;
import com.websocket.util.BeansUtil;
import com.websocket.util.KeyUtil;
import com.websocket.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.tio.core.Aio;
import org.tio.core.ChannelContext;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.utils.lock.SetWithLock;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsResponse;
import org.tio.websocket.common.WsSessionContext;
import org.tio.websocket.server.handler.IWsMsgHandler;
public class ShowcaseWsMsgHandler implements IWsMsgHandler{
	private static Logger log = LoggerFactory.getLogger(ShowcaseWsMsgHandler.class);
	public static ShowcaseWsMsgHandler me = new ShowcaseWsMsgHandler();
	//获取token
	private StringRedisTemplate redisTemplate = BeansUtil.getBean(StringRedisTemplate.class);
	private OtoWechatServiceImpl otoWechatService = BeansUtil.getBean(OtoWechatServiceImpl.class);  //获取Spring的该实例
	//private UserRepository userRepository = BeansUtil.getBean(UserRepository.class);
	private UserServiceImpl userService = BeansUtil.getBean(UserServiceImpl.class);
	private OtoWechatRepository otoWechatRepository = BeansUtil.getBean(OtoWechatRepository.class);  //获取Spring的该实例;
	private UserInfoRepository userInfoRepository = BeansUtil.getBean(UserInfoRepository.class);
	//获取会话列表
	private DialogueListRepository dialogueListRepository = BeansUtil.getBean(DialogueListRepository.class);  //获取Spring的该实例
	private ShowcaseWsMsgHandler() {
	}


	/**
	 * 握手时走这个方法，业务可以在这里获取cookie，request参数等
	 */
	@Override
	public HttpResponse handshake(HttpRequest request, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
		String clientip = request.getClientIp();
		//log.info("收到来自{}的ws握手包\r\n{}", clientip, request.toString());
		return httpResponse;
	}

	/** 
	 * @param httpRequest
	 * @param httpResponse
	 * @param channelContext
	 * @throws Exception
	 *
	 */
	@Override
	public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
		String token = httpRequest.getParam("token");
		String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.LOGIN_SUCCESS_TOKEN, token));
		System.out.println("token Value:"+tokenValue);
//		if(tokenValue==null){
//			System.err.println("没有登陆状态");
//			Aio.remove(channelContext, "receive close flag");
//			return;
//		}
		User_ user_ = userService.findByPhone(tokenValue);
		String toUserid = httpRequest.getParam("toUserid");  //获取跟哪个用户聊天
		String userid = user_.getUserId().toString();  //获取本身id
		//绑定用户信息
		Aio.bindUser(channelContext,userid);  //握手绑定用户

		if(toUserid!=null){     //获取会话列表，表示在一对一对话框内

		}else{    //获取会话列表，表示不在一对一对话框内
			//用tio-websocket，服务器发送到客户端的Packet都是WsResponse
			String json = "未能获取未收到的聊天";
			try {
				List<WechatDTO> wechatDTOList = otoWechatService.findByToUseridAndFlag
						(userid,1);
				if(wechatDTOList==null){
					//会话列表为空
				}else{
					//废弃 在会话列表设置为已读
				//	for (WechatDTO wechatDTO : wechatDTOList) {
				//		wechatDTO.setFlag(0);    //设置消息为已读
				//	sys
					otoWechatRepository.saveAll(wechatDTOList);
					WebsocketDTO<WechatDTO> wechatDTOWebsocketDTO = new WebsocketDTO<>();
					wechatDTOWebsocketDTO.setFlag(0);   //消息结构为0
					wechatDTOWebsocketDTO.setData(wechatDTOList);
					json = JSON.toJSONString(wechatDTOWebsocketDTO);
					WsResponse wsResponse2 =  WsResponse.fromText(json, ShowcaseServerConfig.CHARSET);
					Aio.sendToUser(channelContext.getGroupContext(),userid,wsResponse2);
				}
			}catch(Exception e){
				e.printStackTrace();
				log.error(httpRequest.getParam("userid")+"会话读取失败");
			}

			List<DialogueList> dialogueLists =
					dialogueListRepository.findByUserid1AndFlagOrderByCreateTimeDesc(user_.getUserId(),FlagEnum.NO_DELETE.getCode());

			if(dialogueLists==null){

			}else {
				List<DialogueListForUserinfo> dialogueListForUserinfos = new ArrayList<>();
				for (DialogueList dialogueList : dialogueLists) {
					DialogueListForUserinfo dialogueListForUserinfo = new DialogueListForUserinfo();
					dialogueListForUserinfo.setDialogueList(dialogueList);
					UserInfo userInfo = userInfoRepository.findByUserId(dialogueList.getUserid2());
					dialogueListForUserinfo.setImgUrl(userInfo.getImgUrl());
					dialogueListForUserinfo.setNickname(userInfo.getNickName());
					dialogueListForUserinfos.add(dialogueListForUserinfo);
				}
				WebsocketDTO wechatDTOWebsocketDTO = new WebsocketDTO<>();
				wechatDTOWebsocketDTO.setFlag(10);   //会话结构为10
				wechatDTOWebsocketDTO.setData(dialogueListForUserinfos);
				String newJson = JSON.toJSONString(wechatDTOWebsocketDTO);
				WsResponse wsResponse3 = WsResponse.fromText(newJson, ShowcaseServerConfig.CHARSET);
				Aio.sendToUser(channelContext.getGroupContext(), userid, wsResponse3);
			}


		}

	}

	/**
	 * 字节消息（binaryType = arraybuffer）过来后会走这个方法
	 */
	@Override
	public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		return null;
	}

	/**
	 * 当客户端发close flag时，会走这个方法
	 */
	@Override
	public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		Aio.remove(channelContext, "receive close flag");
		return null;
	}

	/*
	 * 字符消息（binaryType = blob）过来后会走这个方法
	 */
	@Override
	public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) {

		Date time = new Date();
		WsSessionContext wsSessionContext = (WsSessionContext) channelContext.getAttribute();

		HttpRequest httpRequest = wsSessionContext.getHandshakeRequestPacket();//获取websocket握手包
		String token = httpRequest.getParam("token");
		String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.LOGIN_SUCCESS_TOKEN, token));
		User_ user =  userService.findByPhone(tokenValue);
		if (log.isDebugEnabled()) {
			//log.debug("握手包:{}", httpRequest);
		}
		//log.info("收到ws消息:{}", text);
		if (Objects.equals("心跳内容", text)) {
			return null;
		}
		//String msg2 = channelContext.getClientNode().toString() + " 发送消息成功但对方处于离线中，人家上线就看的到啦" + text;
		log.warn("channelId"+channelContext.getId());
		SetWithLock<ChannelContext> channelContextSetWithLock =
			Aio.getChannelContextsByUserid(channelContext.getGroupContext(),httpRequest.getParam("toUserid"));

			WechatDTO wechatDTO = new WechatDTO();
			wechatDTO.setUserid(user.getUserId().toString());
			wechatDTO.setToUserid(httpRequest.getParam("toUserid"));
			wechatDTO.setCreate_time(new Date());
			wechatDTO.setContent(StringUtils.replaceBlank(text));
			wechatDTO.set_id(KeyUtil.genUniqueKey());
			wechatDTO.setFlag(1);   //改为不管在不在都设为未接受
			System.err.println("if的判断："+channelContextSetWithLock);
			if(channelContextSetWithLock==null){  //判断是否在线
				wechatDTO.setFlag(1);
		//		WsResponse wsResponse = WsResponse.fromText(msg2, ShowcaseServerConfig.CHARSET);
		//		Aio.sendToUser(channelContext.getGroupContext(),httpRequest.getParam("userid"),wsResponse);
			}else{
				WsResponse wsResponse = WsResponse.fromText(JSON.toJSONString(wechatDTO), ShowcaseServerConfig.CHARSET);
				Aio.sendToUser(channelContext.getGroupContext(),httpRequest.getParam("toUserid"),wsResponse);
			}
				otoWechatRepository.save(wechatDTO);   //消息记录的保存
		try {

			DialogueList dialogue1 =
			dialogueListRepository.findByUserid1AndUserid2AndFlag(
					user.getUserId(),
					Integer.valueOf(httpRequest.getParam("toUserid")),
					FlagEnum.NO_DELETE.getCode());
			DialogueList dialogueList = new DialogueList();

			if(dialogue1==null){   //还未发生过对话或者已删除对话
				dialogueList.set_id(KeyUtil.genUniqueKey());
				dialogueList.setData(wechatDTO);
				dialogueList.setFlag(FlagEnum.NO_DELETE.getCode());
				dialogueList.setUserid1(user.getUserId());
				dialogueList.setUserid2(Integer.valueOf(httpRequest.getParam("toUserid")));
				dialogueList.setCreateTime(time);
				dialogueListRepository.save(dialogueList);
				//反过来查询对方是否有该对话列表
				DialogueList dialogue2 =
						dialogueListRepository.findByUserid1AndUserid2AndFlag(
								Integer.valueOf(httpRequest.getParam("toUserid")),
								user.getUserId(),
								FlagEnum.NO_DELETE.getCode());
				if(dialogue2==null){   //对方不存在该会话
					dialogueList.set_id(KeyUtil.genUniqueKey());
					dialogueList.setUserid1(Integer.valueOf(httpRequest.getParam("toUserid")));
					dialogueList.setUserid2(user.getUserId());
					dialogueList.setCreateTime(time);

					dialogueListRepository.save(dialogueList);
				}else{  //存在则更新最新内容
					dialogue2.setData(wechatDTO);  //更新最后的内容;
					dialogue2.setCreateTime(time);
					dialogueListRepository.save(dialogue2);
				}
			}else{  //已发生过对话
//				更新最新内容
				dialogue1.setData(wechatDTO);
				dialogue1.setCreateTime(time);
				dialogueListRepository.save(dialogue1);
				//重复代码
				//反过来查询对方是否有该对话列表
				DialogueList dialogue2 =
						dialogueListRepository.findByUserid1AndUserid2AndFlag(
								Integer.valueOf(httpRequest.getParam("toUserid")),
								user.getUserId(),
								FlagEnum.NO_DELETE.getCode());
				if(dialogue2==null){   //对方不存在该会话
					dialogue1.set_id(KeyUtil.genUniqueKey());
					dialogue1.setUserid1(Integer.valueOf(httpRequest.getParam("toUserid")));
					dialogue1.setUserid2(user.getUserId());
					dialogue1.setCreateTime(time);
					dialogueListRepository.save(dialogue1);
				}else{  //存在则更新最新内容
					dialogue2.setData(wechatDTO);  //更新最后的内容;
					dialogue2.setCreateTime(time);
					dialogueListRepository.save(dialogue2);
				}
			}
		}catch (Exception e){
			e.printStackTrace();
			System.err.println("会话存储失败");
		}
		return null;
	}
}
